home *** CD-ROM | disk | FTP | other *** search
/ The 640 MEG Shareware Studio 2 / The 640 Meg Shareware Studio CD-ROM Volume II (Data Express)(1993).ISO / os2 / os2maz.zip / OS2MAZE.C < prev    next >
C/C++ Source or Header  |  1992-03-07  |  70KB  |  1,802 lines

  1. /*
  2.          This OS/2 1.3 program will generate a three dimensional maze on a VGA
  3.     display.  A different random number seed will produce a different maze.
  4.  
  5.          Written on March 7, 1992 by James L. Dean
  6.                                      406 40th Street
  7.                                      New Orleans, LA 70124
  8. */
  9. #include <stdio.h>
  10. #include <string.h>
  11. #include <math.h>
  12. #include <malloc.h>
  13. #include <memory.h>
  14. #include <stdlib.h>
  15. #include <conio.h>
  16. #include <dos.h>
  17. #define INCL_BASE
  18. #include <os2.h>
  19.  
  20. #define TRUE 1
  21. #define FALSE 0
  22.  
  23. /* screen constants */
  24. #define WIDTH_OF_SCREEN           8.0
  25. #define HEIGHT_OF_SCREEN          6.0 /* same units as WIDTH_OF_SCREEN */
  26.  
  27. /* graphics constants */
  28. #define NUM_X_PIXELS            640
  29. #define NUM_Y_PIXELS            480
  30. #define NUM_COLORS               16
  31. #define RGB_INCREMENT             4     /* 64/NUM_COLORS */
  32. #define stack_size            32767
  33. #define NUM_CELLS             38400     /* NUM_X_PIXELS*NUM_Y_PIXELS/8 */
  34. #define VGA_control           0x3ce     /* graphics controller control port */
  35. #define VGA_control_data      0x3cf     /* graphics controller data port */
  36. #define VGA_read_map           0x04     /* read map register in graphics port */
  37. #define VGA_mode               0x05     /* mode register in graphics port */
  38. #define VGA_bit_mask           0x08     /* bitmask register in graphics port */     
  39. #define VGA_sequence          0x3c4     /* sequencer control port */
  40. #define VGA_sequence_data     0x3c5     /* sequencer data port   */
  41. #define VGA_map_mask           0x02     /* map mask register in sequencer */
  42.  
  43. /* maze constants */
  44. #define NUM_COLUMNS             24
  45. #define MAX_X                   48      /* 2*NUM_COLUMNS */
  46. #define MAX_X_PLUS_1            49      /* MAX_X+1 */
  47. #define MAX_X_LESS_1            47      /* MAX_X-1 */
  48. #define NUM_ROWS                18
  49. #define MAX_Y                   36      /* 2*NUM_ROWS */
  50. #define MAX_Y_PLUS_1            37      /* MAX_Y+1 */
  51. #define MAX_Y_LESS_1            35      /* MAX_Y-1 */
  52. #define NUM_ROOMS_IN_MAZE      432      /* NUM_ROWS*NUM_COLUMNS */
  53. #define RESOLUTION               4      /* larger numbers give more detail
  54.                                            but take more time and memory */
  55.  
  56. typedef struct
  57.           {
  58.             int   x;
  59.             int   y;
  60.           } box_rec;
  61.  
  62. typedef struct
  63.           {
  64.             unsigned char red;
  65.             unsigned char green;
  66.             unsigned char blue;
  67.           } rgb_rec;
  68.  
  69. typedef struct
  70.           {
  71.             double x;
  72.             double y;
  73.             double z;
  74.           } vertex_rec;
  75.  
  76. static void   add_room(void);
  77. static void   adjust_perspective(int,int,float huge *,float huge *,float huge *,
  78.                double,double,double,double,double);
  79. static void   clear_screen(void);
  80. static void   evaluate_and_transform(double,double,double,double,int,int,
  81.                double,double,float huge *,float huge *,float huge *,double *,
  82.                double *,double *,double *,double *,vertex_rec *,vertex_rec *,
  83.                int huge *,int huge *,unsigned char huge *);
  84. static double f(double,double);
  85. static void   free_memory(float huge **,float huge **,float huge **,int huge **,
  86.                int huge **,unsigned char huge **,unsigned char huge **);
  87. static void   generate_maze(void);
  88. static void   get_cursor(USHORT *,USHORT *,VIOCURSORINFO *);
  89. static void   hash(int *,int *,int *,int *,int *,int *,int *,int *);
  90. static void   increment(int *,int *,int *,int *,int *,int *,int *,int *);
  91.        void   main(void);
  92. static int    memory_allocated(long,float huge **,float huge **,float huge **,
  93.                int huge **,int huge **,unsigned char huge **,
  94.                unsigned char huge **);
  95. static void   mode_thread(void);
  96. static int    num_rooms_in_solution(void);
  97. static void   plot(int,int huge *,int,int huge *,long,float huge *,float huge *,
  98.                double,double,double,double,unsigned char huge *,
  99.                unsigned char huge *,int);
  100. static void   save_redraw_thread(void);
  101. static void   set_cursor_position(USHORT,USHORT);
  102. static void   set_cursor_type(VIOCURSORINFO *);
  103. static void   set_initial_video_mode(void);
  104. static void   set_pixel(int,int,short);
  105. static void   shade(int,int,float huge *,float huge *,float huge *,
  106.                unsigned char huge *,vertex_rec *);
  107. static void   sort_back_to_front(long,float huge *,int huge *,int huge *);
  108. static void   titillate(void);
  109. static int    VGA_640_480_16(void);
  110.  
  111. static USHORT        cursor_column;
  112. static USHORT        cursor_row;
  113. static int           delta_x [4] [24];
  114. static int           delta_y [4] [24];
  115.        VIOCURSORINFO initial_cursor_type;
  116. static char          page [MAX_Y_PLUS_1] [MAX_X_PLUS_1];
  117. static int           r_n [8];
  118. static int           r_n_index_1;
  119. static int           r_n_index_2;
  120. static int           tem_int;
  121. static char          titillator [4] = { '|', '/', '-', '\\' };
  122.        VIOCURSORINFO titillator_cursor_type;
  123. static int           titillator_index;
  124. static int           x_maze;
  125. static int           x_next;
  126. static int           x_wall;
  127. static int           y_maze;
  128. static int           y_next;
  129. static int           y_wall;
  130.  
  131. /* video globals */
  132.  
  133.        VIOMODEINFO   default_video_mode;
  134.        PVIOPALSTATE  invisible_palette;
  135.        BYTE          invisible_palette_byte [38];
  136.        VIOCOLORREG   maze_color;
  137.        PVIOPALSTATE  maze_palette;
  138.        BYTE          maze_palette_byte [38];
  139. static rgb_rec       maze_rgb [16];
  140.        VIOMODEINFO   maze_video_mode;
  141. static int           mode_id;
  142. static char          mode_thread_stack [stack_size];
  143.        VIOPHYSBUF    phys_buf;
  144. static char          save_redraw_thread_stack [stack_size];
  145. static int           save_redraw_id;
  146. static unsigned char scr_lock;    
  147. static int           VGA_base_adr;
  148. static long huge     *video_plane [4];  /* save area for video planes */
  149.  
  150. void main()
  151.   {
  152.     static unsigned char huge *color;
  153.     static vertex_rec         light;
  154.     static vertex_rec         light_prime;
  155.     static int                num_x_divisions;
  156.     static long               num_primes;
  157.     static int                num_y_divisions;
  158.     static int                response;
  159.     static double             rotation;
  160.     static unsigned char huge *base_z;
  161.     static double             tilt;
  162.     static int huge           *x_division_index;
  163.     static double             x_max;
  164.     static double             x_min;
  165.     static float huge         *x_prime;
  166.     static double             x_prime_max;
  167.     static int huge           *y_division_index;
  168.     static double             y_max;
  169.     static double             y_min;
  170.     static float huge         *y_prime;
  171.     static double             y_prime_max;
  172.     static double             y_prime_min;
  173.     static float huge         *z_prime;
  174.     static double             z_prime_max;
  175.     static double             z_prime_min;
  176.  
  177.     num_x_divisions=RESOLUTION*(MAX_Y+2)+1;
  178.     num_y_divisions=RESOLUTION*(MAX_X+2)+1;
  179.     num_primes=(long) num_x_divisions;
  180.     num_primes*=((long) num_y_divisions);
  181.     if (memory_allocated(num_primes,&x_prime,&y_prime,
  182.      &z_prime,&x_division_index,&y_division_index,&color,&base_z))
  183.       {
  184.         clear_screen();
  185.         printf("                                 Maze Generator\n\n\n\n");
  186.         printf(
  187.         "     After the maze is displayed, press \"S\" to see the solution.\n");
  188.         generate_maze();
  189.         x_min=1.0;
  190.         x_max=(double) num_x_divisions;
  191.         y_min=1.0;
  192.         y_max=(double) num_y_divisions;
  193.         rotation=0.0;
  194.         tilt=30.0; /* must be < 90.0 if solution is to be displayed correctly */
  195.         light.x=0.0;
  196.         light.y=-1.0;
  197.         light.z=3.0;
  198.         evaluate_and_transform(x_min,x_max,y_min,y_max,num_x_divisions,
  199.          num_y_divisions,rotation,tilt,x_prime,y_prime,z_prime,&x_prime_max,
  200.          &y_prime_min,&y_prime_max,&z_prime_min,&z_prime_max,&light,
  201.          &light_prime,x_division_index,y_division_index,base_z);
  202.         shade(num_x_divisions,num_y_divisions,x_prime,y_prime,z_prime,color,
  203.          &light_prime);
  204.         adjust_perspective(num_x_divisions,num_y_divisions,x_prime,y_prime,
  205.          z_prime,x_prime_max,y_prime_min,y_prime_max,z_prime_min,z_prime_max);
  206.         sort_back_to_front(num_primes,x_prime,x_division_index,
  207.          y_division_index);
  208.         if (VGA_640_480_16())
  209.           {
  210.             plot(num_x_divisions,x_division_index,num_y_divisions,
  211.              y_division_index,num_primes,y_prime,z_prime,y_prime_min,
  212.              y_prime_max,z_prime_min,z_prime_max,color,base_z,FALSE);
  213.             fflush(stdin);
  214.             response=getch();
  215.             fflush(stdin);
  216.             if ((response == (int) 's') || (response == (int) 'S'))
  217.               {
  218.                 plot(num_x_divisions,x_division_index,num_y_divisions,
  219.                  y_division_index,num_primes,y_prime,z_prime,y_prime_min,
  220.                  y_prime_max,z_prime_min,z_prime_max,color,base_z,TRUE);
  221.                 fflush(stdin);
  222.                 response=getch();
  223.                 fflush(stdin);
  224.               }
  225.             set_initial_video_mode();
  226.           }
  227.         else
  228.           printf("? 640 x 480 x 16 VGA mode is not available\n");
  229.         set_cursor_type(&initial_cursor_type);
  230.         free_memory(&x_prime,&y_prime,&z_prime,&x_division_index,
  231.          &y_division_index,&color,&base_z);
  232.       }
  233.     else
  234.       printf("? not enough memory\n");
  235.     return;
  236.   }
  237.  
  238. static void clear_screen()
  239.   {
  240.     unsigned char fill [2];
  241.     VIOMODEINFO   video_mode_info;
  242.  
  243.     video_mode_info.cb=(unsigned int) 12;
  244.     VioGetMode(&video_mode_info,(HVIO) 0);
  245.     fill[0]=(unsigned char) ' ';
  246.     fill[1]=(unsigned char) 7;
  247.     VioScrollUp((USHORT) 0,(USHORT) 0,
  248.      (USHORT) (video_mode_info.row-1),
  249.      (USHORT) (video_mode_info.col-1),
  250.      (USHORT) 0xffff,(PBYTE) &fill[0],(HVIO) 0);
  251.     VioSetCurPos((USHORT) 0,(USHORT) 0,(HVIO) 0);
  252.     return;
  253.   }
  254.  
  255. static void get_cursor(cursor_row,cursor_column,cursor_type)
  256.   USHORT        *cursor_row;
  257.   USHORT        *cursor_column;
  258.   VIOCURSORINFO *cursor_type;
  259.     {
  260.       VioGetCurPos((PUSHORT) cursor_row,(PUSHORT) cursor_column,(HVIO) 0);
  261.       VioGetCurType((PVIOCURSORINFO) cursor_type,(HVIO) 0);
  262.       return;
  263.     }
  264.  
  265. static void set_cursor_position(cursor_row,cursor_column)
  266.   USHORT cursor_row;
  267.   USHORT cursor_column;
  268.     {
  269.       VioSetCurPos(cursor_row,cursor_column,(HVIO) 0);
  270.       return;
  271.     }
  272.  
  273. static void set_cursor_type(cursor_type)
  274.   VIOCURSORINFO *cursor_type;
  275.     {
  276.       VioSetCurType((PVIOCURSORINFO) cursor_type,(HVIO) 0);
  277.       return;
  278.     }
  279.  
  280. static void titillate()
  281.     {
  282.       set_cursor_position(cursor_row,cursor_column);
  283.       titillator_index++;
  284.       if (titillator_index > 3)
  285.         titillator_index=0;
  286.       putchar((int) titillator[titillator_index]);
  287.       return;
  288.     }
  289.  
  290. static int memory_allocated(num_primes,x_prime,y_prime,
  291.  z_prime,x_division_index,y_division_index,color,base_z)
  292.   long               num_primes;
  293.   float huge         **x_prime;
  294.   float huge         **y_prime;
  295.   float huge         **z_prime;
  296.   int   huge         **x_division_index;
  297.   int   huge         **y_division_index;
  298.   unsigned char huge **color;
  299.   unsigned char huge **base_z;
  300.     {
  301.       static int  result;
  302.  
  303.       result
  304.        =((*x_prime=(float huge *) halloc(num_primes,sizeof(float))) != NULL);
  305.       if (result)
  306.         {
  307.           if (! (result=((*y_prime
  308.            =(float huge *) halloc(num_primes,sizeof(float))) != NULL)))
  309.             hfree((void huge *) *x_prime);
  310.         }
  311.       if (result)
  312.         {
  313.           if (! (result=((*z_prime
  314.            =(float huge *) halloc(num_primes,sizeof(float))) != NULL)))
  315.             {
  316.               hfree((void huge *) *y_prime);
  317.               hfree((void huge *) *x_prime);
  318.             }
  319.         }
  320.       if (result)
  321.         {
  322.           if (! (result=((*x_division_index
  323.            =(int huge *) halloc(num_primes,sizeof(int))) != NULL)))
  324.             {
  325.               hfree((void huge *) *z_prime);
  326.               hfree((void huge *) *y_prime);
  327.               hfree((void huge *) *x_prime);
  328.             }
  329.         }
  330.       if (result)
  331.         {
  332.           if (! (result=((*y_division_index
  333.            =(int huge *) halloc(num_primes,sizeof(int))) != NULL)))
  334.             {
  335.               hfree((void huge *) *x_division_index);
  336.               hfree((void huge *) *z_prime);
  337.               hfree((void huge *) *y_prime);
  338.               hfree((void huge *) *x_prime);
  339.             }
  340.         }
  341.       if (result)
  342.         {
  343.           if (! (result=((*color=(unsigned char huge *) 
  344.            halloc(num_primes,sizeof(unsigned char))) != NULL)))
  345.             {
  346.               hfree((void huge *) *y_division_index);
  347.               hfree((void huge *) *x_division_index);
  348.               hfree((void huge *) *z_prime);
  349.               hfree((void huge *) *y_prime);
  350.               hfree((void huge *) *x_prime);
  351.             }
  352.         }
  353.       if (result)
  354.         {
  355.           if (! (result=((*base_z=(unsigned char huge *) 
  356.            halloc(num_primes,sizeof(unsigned char))) != NULL)))
  357.             {
  358.               hfree((void huge *) *color);
  359.               hfree((void huge *) *y_division_index);
  360.               hfree((void huge *) *x_division_index);
  361.               hfree((void huge *) *z_prime);
  362.               hfree((void huge *) *y_prime);
  363.               hfree((void huge *) *x_prime);
  364.             }
  365.         }
  366.       return(result);
  367.     }
  368.  
  369. static void generate_maze()
  370.     {
  371.       static   int  counter_0;
  372.       static   int  counter_1;
  373.       static   int  counter_2;
  374.       static   int  counter_3;
  375.       static   int  counter_4;
  376.       static   int  counter_5;
  377.       static   int  counter_6;
  378.       static   int  counter_7;
  379.       static   int  delta_index_1a;
  380.       static   int  delta_index_1b;
  381.       static   int  delta_index_1c;
  382.       static   int  delta_index_1d;
  383.       static   int  delta_index_2;
  384.       static   int  digit;
  385.       static   int  digit_num;
  386.       static   char seed [256];
  387.       static   int  seed_length;
  388.       static   int  sum;
  389.       register int  x_out;
  390.       register int  y_out;
  391.  
  392.       printf("\n     Random number seed?  ");
  393.       gets(&seed[0]);
  394.       get_cursor(&cursor_row,&cursor_column,&initial_cursor_type);
  395.       memcpy((void *) &titillator_cursor_type,
  396.        (const void *) &initial_cursor_type,sizeof(VIOCURSORINFO));
  397.       titillator_cursor_type.attr=0xffff;
  398.       set_cursor_type(&titillator_cursor_type);
  399.       titillator_index=0;
  400.       seed_length=strlen(&seed[0]);
  401.       for (r_n_index_1=0; r_n_index_1 < seed_length; ++r_n_index_1)
  402.         r_n[r_n_index_1]=(int) (seed[r_n_index_1] % 10);
  403.       r_n_index_2=7;
  404.       while (r_n_index_1 > 0)
  405.         {
  406.            r_n_index_1--;
  407.            r_n[r_n_index_2]=r_n[r_n_index_1];
  408.            r_n_index_2--;
  409.         }
  410.       while (r_n_index_2 >= 0)
  411.         {
  412.           r_n[r_n_index_2]=0;
  413.           r_n_index_2--;
  414.         }
  415.       counter_0=r_n[1];
  416.       counter_1=r_n[2];
  417.       counter_2=r_n[3];
  418.       counter_3=r_n[4];
  419.       counter_4=r_n[5];
  420.       counter_5=r_n[6];
  421.       counter_6=r_n[7];
  422.       counter_7=r_n[8];
  423.       hash(&counter_0,&counter_1,&counter_2,&counter_3,&counter_4,&counter_5,
  424.        &counter_6,&counter_7);
  425.       delta_x[0][0]=-1;
  426.       delta_y[0][0]=0;
  427.       delta_x[1][0]=0;
  428.       delta_y[1][0]=1;
  429.       delta_x[2][0]=1;
  430.       delta_y[2][0]=0;
  431.       delta_x[3][0]=0;
  432.       delta_y[3][0]=-1;
  433.       delta_index_2=0;
  434.       for (delta_index_1a=0; delta_index_1a < 4; ++delta_index_1a)
  435.         for (delta_index_1b=0; delta_index_1b < 4; ++delta_index_1b)
  436.           if (delta_index_1a != delta_index_1b)
  437.             for (delta_index_1c=0; delta_index_1c < 4; ++delta_index_1c)
  438.               if ((delta_index_1a != delta_index_1c)
  439.               &&  (delta_index_1b != delta_index_1c))
  440.                 for (delta_index_1d=0; delta_index_1d < 4; ++delta_index_1d)
  441.                   if ((delta_index_1a != delta_index_1d)
  442.                   &&  (delta_index_1b != delta_index_1d)
  443.                   &&  (delta_index_1c != delta_index_1d))
  444.                     {
  445.                       delta_x[delta_index_1a][delta_index_2]=delta_x[0][0];
  446.                       delta_y[delta_index_1a][delta_index_2]=delta_y[0][0];
  447.                       delta_x[delta_index_1b][delta_index_2]=delta_x[1][0];
  448.                       delta_y[delta_index_1b][delta_index_2]=delta_y[1][0];
  449.                       delta_x[delta_index_1c][delta_index_2]=delta_x[2][0];
  450.                       delta_y[delta_index_1c][delta_index_2]=delta_y[2][0];
  451.                       delta_x[delta_index_1d][delta_index_2]=delta_x[3][0];
  452.                       delta_y[delta_index_1d][delta_index_2]=delta_y[3][0];
  453.                       delta_index_2++;
  454.                     };
  455.       do
  456.         {
  457.           titillate();
  458.           for (y_out=0; y_out <= MAX_Y; ++y_out)
  459.             for (x_out=0; x_out <= MAX_X; ++x_out)
  460.               page[y_out][x_out]='W';
  461.           r_n[1]=counter_0+1;
  462.           r_n[2]=counter_1+1;
  463.           r_n[3]=counter_2+1;
  464.           r_n[4]=counter_3+1;
  465.           r_n[5]=counter_4+1;
  466.           r_n[6]=counter_5+1;
  467.           r_n[7]=counter_6+1;
  468.           r_n[8]=counter_7+1;
  469.           sum=0;
  470.           for (digit_num=1; digit_num <= 3; ++digit_num)
  471.             {
  472.               digit=r_n[0];
  473.               r_n_index_1=0;
  474.               for (r_n_index_2=1; r_n_index_2 < 8; ++r_n_index_2)
  475.                 {
  476.                   tem_int=r_n[r_n_index_2];
  477.                   r_n[r_n_index_1]=tem_int;
  478.                   digit+=tem_int;
  479.                   if (digit >= 29)
  480.                      digit-=29;
  481.                   r_n_index_1=r_n_index_2;
  482.                 }
  483.               r_n[7]=digit;
  484.               sum=29*sum+digit;
  485.             }
  486.           x_maze=2*(sum % NUM_COLUMNS)+1;
  487.           sum=0;
  488.           for (digit_num=1; digit_num <= 3; ++digit_num)
  489.             {
  490.               digit=r_n[0];
  491.               r_n_index_1=0;
  492.               for (r_n_index_2=1; r_n_index_2 < 8; ++r_n_index_2)
  493.                 {
  494.                   tem_int=r_n[r_n_index_2];
  495.                   r_n[r_n_index_1]=tem_int;
  496.                   digit+=tem_int;
  497.                   if (digit >= 29)
  498.                      digit-=29;
  499.                   r_n_index_1=r_n_index_2;
  500.                 }
  501.               r_n[7]=digit;
  502.               sum=29*sum+digit;
  503.             }
  504.           y_maze=2*(sum % NUM_ROWS)+1;
  505.           add_room();
  506.           page[0][1]=' ';
  507.           page[MAX_Y][MAX_X-1]=' ';
  508.           increment(&counter_0,&counter_1,&counter_2,&counter_3,&counter_4,
  509.            &counter_5,&counter_6,&counter_7);
  510.         }
  511.       while (3*num_rooms_in_solution() < NUM_ROOMS_IN_MAZE);
  512.       return;
  513.     }
  514.  
  515. static int substitution_high [100] =
  516.              { 4,1,2,8,8,9,9,6,5,7,2,1,2,9,8,8,6,3,5,1,9,5,4,4,9,8,6,0,8,0,
  517.                6,0,2,4,1,9,2,0,7,4,7,3,0,0,2,6,8,9,4,0,8,3,2,3,2,5,2,4,6,9,
  518.                7,9,1,3,5,7,1,1,4,5,8,1,6,0,5,7,8,2,3,3,7,3,5,1,7,5,4,0,3,6,
  519.                3,7,7,1,9,4,0,5,6,6 
  520.              };
  521. static int substitution_low [100] =
  522.              { 1,2,2,1,5,5,4,6,4,6,4,4,5,6,6,3,0,9,6,5,7,2,0,9,3,4,2,3,9,1,
  523.                9,9,9,3,8,9,3,4,1,5,0,5,2,7,0,8,8,0,4,5,0,3,6,8,1,7,8,8,7,1,
  524.                3,2,7,7,1,8,0,3,7,5,2,6,4,0,9,9,7,7,4,6,2,0,0,1,7,3,6,6,1,1,
  525.                2,4,5,9,8,2,8,8,3,5 
  526.              };
  527. static void hash(counter_0,counter_1,counter_2,counter_3,counter_4,counter_5,
  528.  counter_6,counter_7)
  529.   int *counter_0;
  530.   int *counter_1;
  531.   int *counter_2;
  532.   int *counter_3;
  533.   int *counter_4;
  534.   int *counter_5;
  535.   int *counter_6;
  536.   int *counter_7;
  537.     {
  538.       register int iteration;
  539.       static   int seed_0;
  540.       static   int seed_1;
  541.       static   int seed_2;
  542.       static   int seed_3;
  543.       static   int seed_4;
  544.       static   int seed_5;
  545.       static   int seed_6;
  546.       static   int seed_7;
  547.       register int substitution_index;
  548.       static   int tem_0;
  549.       static   int tem_1;
  550.       static   int tem_2;
  551.  
  552.       seed_0=(*counter_0);
  553.       seed_1=(*counter_1);
  554.       seed_2=(*counter_2);
  555.       seed_3=(*counter_3);
  556.       seed_4=(*counter_4);
  557.       seed_5=(*counter_5);
  558.       seed_6=(*counter_6);
  559.       seed_7=(*counter_7);
  560.       for (iteration=1; iteration <= 8; iteration++)
  561.         {
  562.           substitution_index=10*seed_1+seed_0;
  563.           tem_0=substitution_low[substitution_index];
  564.           tem_1=substitution_high[substitution_index];
  565.           substitution_index=10*seed_3+seed_2;
  566.           seed_0=substitution_low[substitution_index];
  567.           tem_2=substitution_high[substitution_index];
  568.           substitution_index=10*seed_5+seed_4;
  569.           seed_2=substitution_low[substitution_index];
  570.           seed_1=substitution_high[substitution_index];
  571.           substitution_index=10*seed_7+seed_6;
  572.           seed_5=substitution_low[substitution_index];
  573.           seed_7=substitution_high[substitution_index];
  574.           seed_3=tem_0;
  575.           seed_6=tem_1;
  576.           seed_4=tem_2;
  577.         }
  578.       (*counter_0)=seed_0;
  579.       (*counter_1)=seed_1;
  580.       (*counter_2)=seed_2;
  581.       (*counter_3)=seed_3;
  582.       (*counter_4)=seed_4;
  583.       (*counter_5)=seed_5;
  584.       (*counter_6)=seed_6;
  585.       (*counter_7)=seed_7;
  586.       return;
  587.     }
  588.  
  589. static void increment(counter_0,counter_1,counter_2,counter_3,counter_4,
  590.  counter_5,counter_6,counter_7)
  591.   int *counter_0;
  592.   int *counter_1;
  593.   int *counter_2;
  594.   int *counter_3;
  595.   int *counter_4;
  596.   int *counter_5;
  597.   int *counter_6;
  598.   int *counter_7;
  599.     {
  600.       register tem;
  601.  
  602.       tem=(*counter_0)+1;
  603.       if (tem <= 9)
  604.         (*counter_0)=tem;
  605.       else
  606.         {
  607.           (*counter_0)=0;
  608.           tem=(*counter_1)+1;
  609.           if (tem <= 9)
  610.             (*counter_1)=tem;
  611.           else
  612.             {
  613.               (*counter_1)=0;
  614.               tem=(*counter_2)+1;
  615.               if (tem <= 9)
  616.                 (*counter_2)=tem;
  617.               else
  618.                 {
  619.                   (*counter_2)=0;
  620.                   tem=(*counter_3)+1;
  621.                   if (tem <= 9)
  622.                     (*counter_3)=tem;
  623.                   else
  624.                     {
  625.                       (*counter_3)=0;
  626.                       tem=(*counter_4)+1;
  627.                       if (tem <= 9)
  628.                         (*counter_4)=tem;
  629.                       else
  630.                         {
  631.                           (*counter_4)=0;
  632.                           tem=(*counter_5)+1;
  633.                           if (tem <= 9)
  634.                             (*counter_5)=tem;
  635.                           else
  636.                             {
  637.                               (*counter_5)=0;
  638.                               tem=(*counter_6)+1;
  639.                               if (tem <= 9)
  640.                                 (*counter_6)=tem;
  641.                               else
  642.                                 {
  643.                                   (*counter_6)=0;
  644.                                   tem=(*counter_7)+1;
  645.                                   if (tem <= 9)
  646.                                     (*counter_7)=tem;
  647.                                   else
  648.                                     (*counter_7)=0;
  649.                                 }
  650.                             }
  651.                         }
  652.                     }
  653.                 }
  654.             }
  655.         }
  656.       return;
  657.     }
  658.  
  659. static int num_rooms_in_solution()
  660.     {
  661.       int direction_x;
  662.       int direction_y;
  663.       int initial_direction_x;
  664.       int initial_direction_y;
  665.       int passage_found;
  666.       int result;
  667.       int tem;
  668.       int x;
  669.       int x_next;
  670.       int y;
  671.       int y_next;
  672.  
  673.       result=1;
  674.       x=1;
  675.       y=1;
  676.       page[y][x]='S';
  677.       initial_direction_x=0;
  678.       initial_direction_y=1;
  679.       do
  680.         {
  681.           passage_found=FALSE;
  682.           direction_x=-initial_direction_y;
  683.           direction_y=initial_direction_x;
  684.           while (! passage_found)
  685.             {
  686.               x_next=x+direction_x;
  687.               y_next=y+direction_y;
  688.               if (page[y_next][x_next] != 'W')
  689.                 passage_found=TRUE;
  690.               else
  691.                 {
  692.                   tem=direction_x;
  693.                   direction_x=direction_y;
  694.                   direction_y=-tem;
  695.                 }
  696.             };
  697.           if (page[y_next][x_next] == ' ')
  698.             {
  699.               result++;
  700.               page[y_next][x_next]='S';
  701.               x=x_next+direction_x;
  702.               y=y_next+direction_y;
  703.               page[y][x]='S';
  704.             }
  705.           else
  706.             {
  707.               result--;
  708.               page[y][x]=' ';
  709.               page[y_next][x_next]=' ';
  710.               x=x_next+direction_x;
  711.               y=y_next+direction_y;
  712.             };
  713.           initial_direction_x=direction_x;
  714.           initial_direction_y=direction_y;
  715.         }
  716.       while ((x != MAX_X_LESS_1) || (y != MAX_Y_LESS_1));
  717.       return(result);
  718.     }
  719.  
  720. static void add_room()
  721.     {
  722.       unsigned char delta_index_1;
  723.       unsigned char delta_index_2;
  724.  
  725.       page[y_maze][x_maze]=' ';
  726.       delta_index_1=0;
  727.       do
  728.         {
  729.           delta_index_2=(unsigned char) r_n[0];
  730.           r_n_index_1=0;
  731.           for (r_n_index_2=1; r_n_index_2 < 8; ++r_n_index_2)
  732.             {
  733.               tem_int=r_n[r_n_index_2];
  734.               r_n[r_n_index_1]=tem_int;
  735.               delta_index_2+=(unsigned char) tem_int;
  736.               if (delta_index_2 >= 29)
  737.                 delta_index_2-=29;
  738.               r_n_index_1=r_n_index_2;
  739.             }
  740.           r_n[7]=delta_index_2;
  741.         }
  742.       while (delta_index_2 >= 24);
  743.       while (delta_index_1 < 4)
  744.         {
  745.           x_next=x_maze+2*delta_x[delta_index_1][delta_index_2];
  746.           if ((x_next <= 0) || (x_next >= MAX_X))
  747.             delta_index_1++;
  748.           else
  749.             {
  750.               y_next=y_maze+2*delta_y[delta_index_1][delta_index_2];
  751.               if ((y_next <= 0) || (y_next >= MAX_Y))
  752.                 delta_index_1++;
  753.               else
  754.                 if (page[y_next][x_next] == 'W')
  755.                   {
  756.                     if (x_maze == x_next)
  757.                       {
  758.                         y_wall=(y_maze+y_next)/2;
  759.                         page[y_wall][x_next]=' ';
  760.                       }
  761.                     else
  762.                       {
  763.                         x_wall=(x_maze+x_next)/2;
  764.                         page[y_next][x_wall]=' ';
  765.                       }
  766.                     x_maze=x_next;
  767.                     y_maze=y_next;
  768.                     add_room();
  769.                     x_maze-=2*delta_x[delta_index_1][delta_index_2];
  770.                     y_maze-=2*delta_y[delta_index_1][delta_index_2];
  771.                   }
  772.                 else
  773.                   delta_index_1++;
  774.             }
  775.         }
  776.     }
  777.  
  778. static void evaluate_and_transform(x_min,x_max,y_min,y_max,num_x_divisions,
  779.  num_y_divisions,rotation,tilt,x_prime,y_prime,z_prime,x_prime_max,y_prime_min,
  780.  y_prime_max,z_prime_min,z_prime_max,light,light_prime,x_division_index,
  781.  y_division_index,base_z)
  782.   double             x_min;
  783.   double             x_max;
  784.   double             y_min;
  785.   double             y_max;
  786.   int                num_x_divisions;
  787.   int                num_y_divisions;
  788.   double             rotation;
  789.   double             tilt;
  790.   float huge         *x_prime;
  791.   float huge         *y_prime;
  792.   float huge         *z_prime;
  793.   double             *x_prime_max;
  794.   double             *y_prime_min;
  795.   double             *y_prime_max;
  796.   double             *z_prime_min;
  797.   double             *z_prime_max;
  798.   vertex_rec         *light;
  799.   vertex_rec         *light_prime;
  800.   int huge           *x_division_index;
  801.   int huge           *y_division_index;
  802.   unsigned char huge *base_z;
  803.     {
  804.       static   double cos_rotation;
  805.       static   double cos_tilt;
  806.       static   double magnitude;
  807.       static   long   prime_num;
  808.       static   double radians;
  809.       static   double radians_per_degree;
  810.       static   double sin_rotation;
  811.       static   double sin_tilt;
  812.       static   double x;
  813.       static   double x_delta;
  814.       register int    x_division_num;
  815.       static   double x_rotated;
  816.       static   double y;
  817.       static   double y_delta;
  818.       register int    y_division_num;
  819.       static   double z;
  820.  
  821.       radians_per_degree=atan(1.0)/45.0;
  822.       radians=tilt*radians_per_degree;
  823.       cos_tilt=cos(radians);
  824.       sin_tilt=sin(radians);
  825.       radians=rotation*radians_per_degree;
  826.       cos_rotation=cos(radians);
  827.       sin_rotation=sin(radians);
  828.       z=fabs(f(x_min,y_min));
  829.       x_rotated=x_min*cos_rotation+y_min*sin_rotation;
  830.       *y_prime_min=-x_min*sin_rotation+y_min*cos_rotation;
  831.       *z_prime_min=-x_rotated*sin_tilt+z*cos_tilt;
  832.       *y_prime_max=*y_prime_min;
  833.       *z_prime_max=*z_prime_min;
  834.       *x_prime_max=x_rotated*cos_tilt+z*sin_tilt;
  835.       x_delta=(double) (num_x_divisions-1);
  836.       x_delta=(x_max-x_min)/x_delta;
  837.       y_delta=(double) (num_y_divisions-1);
  838.       y_delta=(y_max-y_min)/y_delta;
  839.       x=x_min;
  840.       prime_num=0l;
  841.       for (x_division_num=0; x_division_num < num_x_divisions; x_division_num++)
  842.         {
  843.           titillate();
  844.           y=y_min;
  845.           for (y_division_num=0; y_division_num < num_y_divisions;
  846.            y_division_num++)
  847.             {
  848.               z=f(x,y);
  849.               if (z > 0.0)
  850.                 base_z[prime_num]=(unsigned char) 1;
  851.               else
  852.                 if (z < 0.0)
  853.                   base_z[prime_num]=(unsigned char) 2;
  854.                 else
  855.                   base_z[prime_num]=(unsigned char) 0;
  856.               z=fabs(z);
  857.               x_division_index[prime_num]=x_division_num;
  858.               y_division_index[prime_num]=y_division_num;
  859.               x_rotated=x*cos_rotation+y*sin_rotation;
  860.               y_prime[prime_num]=(float) (-x*sin_rotation+y*cos_rotation);
  861.               x_prime[prime_num]=(float) (x_rotated*cos_tilt+z*sin_tilt);
  862.               z_prime[prime_num]=(float) (-x_rotated*sin_tilt+z*cos_tilt);
  863.               if (((double) (x_prime[prime_num])) > *x_prime_max)
  864.                 *x_prime_max=(double) (x_prime[prime_num]);
  865.               if (((double) (y_prime[prime_num])) < *y_prime_min)
  866.                 *y_prime_min=(double) (y_prime[prime_num]);
  867.               if (((double) (y_prime[prime_num])) > *y_prime_max)
  868.                 *y_prime_max=(double) (y_prime[prime_num]);
  869.               if (((double) (z_prime[prime_num])) < *z_prime_min)
  870.                 *z_prime_min=(double) (z_prime[prime_num]);
  871.               if (((double) (z_prime[prime_num])) > *z_prime_max)
  872.                 *z_prime_max=(double) (z_prime[prime_num]);
  873.               y+=y_delta;
  874.               prime_num++;
  875.             }
  876.           x+=x_delta;
  877.         }
  878.       magnitude=(*light).x*(*light).x;
  879.       magnitude+=((*light).y*(*light).y);
  880.       magnitude+=((*light).z*(*light).z);
  881.       magnitude=sqrt(magnitude);
  882.       (*light).x/=magnitude;
  883.       (*light).y/=magnitude;
  884.       (*light).z/=magnitude;
  885.       /* lighting doesn't change with tilt or rotation */
  886.       x_rotated=(*light).x*cos_rotation+(*light).y*sin_rotation;
  887.       (*light_prime).y=-(*light).x*sin_rotation+(*light).y*cos_rotation;
  888.       (*light_prime).z=-x_rotated*sin_tilt+(*light).z*cos_tilt;
  889.       (*light_prime).x=x_rotated*cos_tilt+(*light).z*sin_tilt;
  890.       return;
  891.     }
  892.  
  893. static void shade(num_x_divisions,num_y_divisions,x_prime,y_prime,z_prime,color,
  894.  light_prime)
  895.   int                num_x_divisions;
  896.   int                num_y_divisions;
  897.   float huge         *x_prime;
  898.   float huge         *y_prime;
  899.   float huge         *z_prime;
  900.   unsigned char huge *color;
  901.   vertex_rec         *light_prime;
  902.     {
  903.       static   double     magnitude;
  904.       static   vertex_rec normal;
  905.       static   long       prime_num;
  906.       static   vertex_rec vertex [4];
  907.       register int        x_division_num;
  908.       register int        y_division_num;
  909.  
  910.       prime_num=0l;
  911.       for (x_division_num=0; x_division_num < num_x_divisions;
  912.        x_division_num++)
  913.         {
  914.           titillate();
  915.           for (y_division_num=0; y_division_num < num_y_divisions;
  916.            y_division_num++)
  917.             {
  918.               vertex[0].x=(double) (x_prime[prime_num]);
  919.               vertex[0].y=(double) (y_prime[prime_num]);
  920.               vertex[0].z=(double) (z_prime[prime_num]);
  921.               if (x_division_num < (num_x_divisions-1))
  922.                 if (y_division_num < (num_y_divisions-1))
  923.                   {
  924.                     prime_num+=((long) num_y_divisions);
  925.                     vertex[1].x=(double) (x_prime[prime_num]);
  926.                     vertex[1].y=(double) (y_prime[prime_num]);
  927.                     vertex[1].z=(double) (z_prime[prime_num]);
  928.                     prime_num++;
  929.                     vertex[2].x=(double) (x_prime[prime_num]);
  930.                     vertex[2].y=(double) (y_prime[prime_num]);
  931.                     vertex[2].z=(double) (z_prime[prime_num]);
  932.                     prime_num-=((long) num_y_divisions);
  933.                     vertex[3].x=(double) (x_prime[prime_num]);
  934.                     vertex[3].y=(double) (y_prime[prime_num]);
  935.                     vertex[3].z=(double) (z_prime[prime_num]);
  936.                     prime_num--;
  937.                   }
  938.                 else
  939.                   {
  940.                     prime_num--;
  941.                     vertex[1].x=(double) (x_prime[prime_num]);
  942.                     vertex[1].y=(double) (y_prime[prime_num]);
  943.                     vertex[1].z=(double) (z_prime[prime_num]);
  944.                     prime_num+=((long) num_y_divisions);
  945.                     vertex[2].x=(double) (x_prime[prime_num]);
  946.                     vertex[2].y=(double) (y_prime[prime_num]);
  947.                     vertex[2].z=(double) (z_prime[prime_num]);
  948.                     prime_num++;
  949.                     vertex[3].x=(double) (x_prime[prime_num]);
  950.                     vertex[3].y=(double) (y_prime[prime_num]);
  951.                     vertex[3].z=(double) (z_prime[prime_num]);
  952.                     prime_num-=((long) num_y_divisions);
  953.                   }
  954.               else
  955.                 if (y_division_num < (num_y_divisions-1))
  956.                   {
  957.                     prime_num++;
  958.                     vertex[1].x=(double) (x_prime[prime_num]);
  959.                     vertex[1].y=(double) (y_prime[prime_num]);
  960.                     vertex[1].z=(double) (z_prime[prime_num]);
  961.                     prime_num-=((long) num_y_divisions);
  962.                     vertex[2].x=(double) (x_prime[prime_num]);
  963.                     vertex[2].y=(double) (y_prime[prime_num]);
  964.                     vertex[2].z=(double) (z_prime[prime_num]);
  965.                     prime_num--;
  966.                     vertex[3].x=(double) (x_prime[prime_num]);
  967.                     vertex[3].y=(double) (y_prime[prime_num]);
  968.                     vertex[3].z=(double) (z_prime[prime_num]);
  969.                     prime_num+=((long) num_y_divisions);
  970.                   }
  971.                 else
  972.                   {
  973.                     prime_num-=((long) num_y_divisions);
  974.                     vertex[1].x=(double) (x_prime[prime_num]);
  975.                     vertex[1].y=(double) (y_prime[prime_num]);
  976.                     vertex[1].z=(double) (z_prime[prime_num]);
  977.                     prime_num--;
  978.                     vertex[2].x=(double) (x_prime[prime_num]);
  979.                     vertex[2].y=(double) (y_prime[prime_num]);
  980.                     vertex[2].z=(double) (z_prime[prime_num]);
  981.                     prime_num+=((long) num_y_divisions);
  982.                     vertex[3].x=(double) (x_prime[prime_num]);
  983.                     vertex[3].y=(double) (y_prime[prime_num]);
  984.                     vertex[3].z=(double) (z_prime[prime_num]);
  985.                     prime_num++;
  986.                   }
  987.               normal.x
  988.                =(vertex[1].y-vertex[0].y)*(vertex[3].z-vertex[0].z)
  989.                -(vertex[3].y-vertex[0].y)*(vertex[1].z-vertex[0].z)
  990.                +(vertex[2].y-vertex[1].y)*(vertex[0].z-vertex[1].z)
  991.                -(vertex[0].y-vertex[1].y)*(vertex[2].z-vertex[1].z)
  992.                +(vertex[3].y-vertex[2].y)*(vertex[1].z-vertex[2].z)
  993.                -(vertex[1].y-vertex[2].y)*(vertex[3].z-vertex[2].z)
  994.                +(vertex[0].y-vertex[3].y)*(vertex[2].z-vertex[3].z)
  995.                -(vertex[2].y-vertex[3].y)*(vertex[0].z-vertex[3].z);
  996.               normal.y
  997.                =(vertex[3].x-vertex[0].x)*(vertex[1].z-vertex[0].z)
  998.                -(vertex[1].x-vertex[0].x)*(vertex[3].z-vertex[0].z)
  999.                +(vertex[0].x-vertex[1].x)*(vertex[2].z-vertex[1].z)
  1000.                -(vertex[2].x-vertex[1].x)*(vertex[0].z-vertex[1].z)
  1001.                +(vertex[1].x-vertex[2].x)*(vertex[3].z-vertex[2].z)
  1002.                -(vertex[3].x-vertex[2].x)*(vertex[1].z-vertex[2].z)
  1003.                +(vertex[2].x-vertex[3].x)*(vertex[0].z-vertex[3].z)
  1004.                -(vertex[0].x-vertex[3].x)*(vertex[2].z-vertex[3].z);
  1005.               normal.z
  1006.                =(vertex[1].x-vertex[0].x)*(vertex[3].y-vertex[0].y)
  1007.                -(vertex[3].x-vertex[0].x)*(vertex[1].y-vertex[0].y)
  1008.                +(vertex[2].x-vertex[1].x)*(vertex[0].y-vertex[1].y)
  1009.                -(vertex[0].x-vertex[1].x)*(vertex[2].y-vertex[1].y)
  1010.                +(vertex[3].x-vertex[2].x)*(vertex[1].y-vertex[2].y)
  1011.                -(vertex[1].x-vertex[2].x)*(vertex[3].y-vertex[2].y)
  1012.                +(vertex[0].x-vertex[3].x)*(vertex[2].y-vertex[3].y)
  1013.                -(vertex[2].x-vertex[3].x)*(vertex[0].y-vertex[3].y);
  1014.               if (normal.x < 0.0)
  1015.                 color[prime_num]=NUM_COLORS;
  1016.               else
  1017.                 {
  1018.                   magnitude
  1019.                    =sqrt(normal.x*normal.x+normal.y*normal.y+normal.z*normal.z);
  1020.                   if (magnitude == 0.0)
  1021.                     color[prime_num]=(unsigned char) 0;
  1022.                   else
  1023.                     {
  1024.                       color[prime_num]
  1025.                        =(unsigned char) ((((float) (NUM_COLORS-1))/2.0)*(1.0
  1026.                        +((*light_prime).x*normal.x+(*light_prime).y*normal.y
  1027.                        +(*light_prime).z*normal.z)/magnitude));
  1028.                       if (color[prime_num] >= (unsigned char) (NUM_COLORS-1))
  1029.                         color[prime_num]=(unsigned char) (NUM_COLORS-2);
  1030.                     }
  1031.                 }
  1032.               prime_num++;
  1033.             }
  1034.         }
  1035.       return;
  1036.     }
  1037.  
  1038. static void adjust_perspective(num_x_divisions,num_y_divisions,x_prime,y_prime,
  1039.  z_prime,x_prime_max,y_prime_min,y_prime_max,z_prime_min,z_prime_max)
  1040.   int        num_x_divisions;
  1041.   int        num_y_divisions;
  1042.   float huge *x_prime;
  1043.   float huge *y_prime;
  1044.   float huge *z_prime;
  1045.   double     x_prime_max;
  1046.   double     y_prime_min;
  1047.   double     y_prime_max;
  1048.   double     z_prime_min;
  1049.   double     z_prime_max;  
  1050.     {
  1051.       static   long       prime_num;
  1052.       static   vertex_rec vertex [4];
  1053.       register int        x_division_num;
  1054.       static   double     x_eye;
  1055.       static   double     y_center;
  1056.       register int        y_division_num;
  1057.       static   double     z_center;
  1058.  
  1059.       if ((y_prime_max-y_prime_min) > (z_prime_max-z_prime_min))
  1060.         x_eye=1.1*(y_prime_max-y_prime_min)+x_prime_max;
  1061.       else
  1062.         x_eye=1.1*(z_prime_max-z_prime_min)+x_prime_max;
  1063.       if (((y_prime_max-y_prime_min) > (z_prime_max-z_prime_min))
  1064.       ||  (z_prime_max != z_prime_min))
  1065.         {
  1066.           y_center=(y_prime_max+y_prime_min)/2.0;
  1067.           z_center=(z_prime_max+z_prime_min)/2.0;
  1068.           prime_num=0l;
  1069.           for (x_division_num=0; x_division_num < num_x_divisions;
  1070.            x_division_num++)
  1071.             {
  1072.               titillate();
  1073.               for (y_division_num=0; y_division_num < num_y_divisions;
  1074.                y_division_num++)
  1075.                 {
  1076.                   vertex[0].x=(double) (x_prime[prime_num]);
  1077.                   vertex[0].y=(double) (y_prime[prime_num]);
  1078.                   vertex[0].z=(double) (z_prime[prime_num]);
  1079.                   if (x_division_num < (num_x_divisions-1))
  1080.                     if (y_division_num < (num_y_divisions-1))
  1081.                       {
  1082.                         prime_num+=((long) num_y_divisions);
  1083.                         vertex[1].x=(double) (x_prime[prime_num]);
  1084.                         vertex[1].y=(double) (y_prime[prime_num]);
  1085.                         vertex[1].z=(double) (z_prime[prime_num]);
  1086.                         prime_num++;
  1087.                         vertex[2].x=(double) (x_prime[prime_num]);
  1088.                         vertex[2].y=(double) (y_prime[prime_num]);
  1089.                         vertex[2].z=(double) (z_prime[prime_num]);
  1090.                         prime_num-=((long) num_y_divisions);
  1091.                         vertex[3].x=(double) (x_prime[prime_num]);
  1092.                         vertex[3].y=(double) (y_prime[prime_num]);
  1093.                         vertex[3].z=(double) (z_prime[prime_num]);
  1094.                         prime_num--;
  1095.                       }
  1096.                     else
  1097.                       {
  1098.                         prime_num--;
  1099.                         vertex[1].x=(double) (x_prime[prime_num]);
  1100.                         vertex[1].y=(double) (y_prime[prime_num]);
  1101.                         vertex[1].z=(double) (z_prime[prime_num]);
  1102.                         prime_num+=((long) num_y_divisions);
  1103.                         vertex[2].x=(double) (x_prime[prime_num]);
  1104.                         vertex[2].y=(double) (y_prime[prime_num]);
  1105.                         vertex[2].z=(double) (z_prime[prime_num]);
  1106.                         prime_num++;
  1107.                         vertex[3].x=(double) (x_prime[prime_num]);
  1108.                         vertex[3].y=(double) (y_prime[prime_num]);
  1109.                         vertex[3].z=(double) (z_prime[prime_num]);
  1110.                         prime_num-=((long) num_y_divisions);
  1111.                       }
  1112.                   else
  1113.                     if (y_division_num < (num_y_divisions-1))
  1114.                       {
  1115.                         prime_num++;
  1116.                         vertex[1].x=(double) (x_prime[prime_num]);
  1117.                         vertex[1].y=(double) (y_prime[prime_num]);
  1118.                         vertex[1].z=(double) (z_prime[prime_num]);
  1119.                         prime_num-=((long) num_y_divisions);
  1120.                         vertex[2].x=(double) (x_prime[prime_num]);
  1121.                         vertex[2].y=(double) (y_prime[prime_num]);
  1122.                         vertex[2].z=(double) (z_prime[prime_num]);
  1123.                         prime_num--;
  1124.                         vertex[3].x=(double) (x_prime[prime_num]);
  1125.                         vertex[3].y=(double) (y_prime[prime_num]);
  1126.                         vertex[3].z=(double) (z_prime[prime_num]);
  1127.                         prime_num+=((long) num_y_divisions);
  1128.                       }
  1129.                     else
  1130.                       {
  1131.                         prime_num-=((long) num_y_divisions);
  1132.                         vertex[1].x=(double) (x_prime[prime_num]);
  1133.                         vertex[1].y=(double) (y_prime[prime_num]);
  1134.                         vertex[1].z=(double) (z_prime[prime_num]);
  1135.                         prime_num--;
  1136.                         vertex[2].x=(double) (x_prime[prime_num]);
  1137.                         vertex[2].y=(double) (y_prime[prime_num]);
  1138.                         vertex[2].z=(double) (z_prime[prime_num]);
  1139.                         prime_num+=((long) num_y_divisions);
  1140.                         vertex[3].x=(double) (x_prime[prime_num]);
  1141.                         vertex[3].y=(double) (y_prime[prime_num]);
  1142.                         vertex[3].z=(double) (z_prime[prime_num]);
  1143.                         prime_num++;
  1144.                       }
  1145.                   y_prime[prime_num]=(float) y_center
  1146.                    +(vertex[0].y-y_center)*(x_eye-x_prime_max)
  1147.                    /(x_eye-vertex[0].x);
  1148.                   z_prime[prime_num]=(float) z_center
  1149.                    +(vertex[0].z-z_center)*(x_eye-x_prime_max)
  1150.                    /(x_eye-vertex[0].x);
  1151.                   x_prime[prime_num]=(float)
  1152.                    (-(vertex[0].x+vertex[1].x+vertex[2].x+vertex[3].x)/4.0);
  1153.                   prime_num++;
  1154.                 }
  1155.             }
  1156.          }
  1157.       return;
  1158.     }
  1159.  
  1160. static void sort_back_to_front(num_primes,x_prime,x_division_index,
  1161.  y_division_index)
  1162.   long       num_primes;
  1163.   float huge *x_prime;
  1164.   int huge   *x_division_index;
  1165.   int huge   *y_division_index;
  1166.     {
  1167.       static   int   finished;
  1168.       static   long  key_index_1;
  1169.       static   long  key_index_2;
  1170.       static   long  left;
  1171.       static   long  right;
  1172.       static   float t1;
  1173.       register int   t2;
  1174.       register int   t3;
  1175.  
  1176.       left=num_primes/((long) 2);
  1177.       right=num_primes-1l;
  1178.       t1=x_prime[0];
  1179.       t2=x_division_index[0];
  1180.       t3=y_division_index[0];
  1181.       while (right > 0l)
  1182.         {
  1183.           titillate();
  1184.           if (left > 0l)
  1185.             {
  1186.               left--;
  1187.               t1=x_prime[left];
  1188.               t2=x_division_index[left];
  1189.               t3=y_division_index[left];
  1190.             }
  1191.           else
  1192.             {
  1193.               t1=x_prime[right];
  1194.               t2=x_division_index[right];
  1195.               t3=y_division_index[right];
  1196.               x_prime[right]=x_prime[0];
  1197.               x_division_index[right]=x_division_index[0];
  1198.               y_division_index[right]=y_division_index[0];
  1199.               right--;
  1200.             }
  1201.           if (right > 0l)
  1202.             {
  1203.               finished=FALSE;
  1204.               key_index_2=left;
  1205.               while (! finished)
  1206.                 {
  1207.                   key_index_1=key_index_2;
  1208.                   key_index_2+=key_index_2;
  1209.                   key_index_2++;
  1210.                   if (key_index_2 > right)
  1211.                     finished=TRUE;
  1212.                   else
  1213.                     {
  1214.                       if (key_index_2 != right)
  1215.                         {
  1216.                           if (x_prime[key_index_2] > x_prime[key_index_2+1])
  1217.                             key_index_2++;
  1218.                         }
  1219.                       if (t1 <= x_prime[key_index_2])
  1220.                         finished=TRUE;
  1221.                       else
  1222.                         {
  1223.                           x_prime[key_index_1]=x_prime[key_index_2];
  1224.                           x_division_index[key_index_1]
  1225.                            =x_division_index[key_index_2];
  1226.                           y_division_index[key_index_1]
  1227.                            =y_division_index[key_index_2];
  1228.                         }
  1229.                     }
  1230.                 }
  1231.               x_prime[key_index_1]=t1;
  1232.               x_division_index[key_index_1]=t2;
  1233.               y_division_index[key_index_1]=t3;
  1234.             }
  1235.         }
  1236.       x_prime[0]=t1;
  1237.       x_division_index[0]=t2;
  1238.       y_division_index[0]=t3;
  1239.       return;
  1240.     }
  1241.  
  1242. static void plot(num_x_divisions,x_division_index,num_y_divisions,
  1243.  y_division_index,num_primes,y_prime,z_prime,y_prime_min,y_prime_max,z_prime_min,
  1244.  z_prime_max,color,base_z,solve)
  1245.   int                num_x_divisions;
  1246.   int huge           *x_division_index;
  1247.   int                num_y_divisions;
  1248.   int huge           *y_division_index;
  1249.   long               num_primes;
  1250.   float huge         *y_prime;
  1251.   float huge         *z_prime;
  1252.   double             y_prime_min;
  1253.   double             y_prime_max;
  1254.   double             z_prime_min;
  1255.   double             z_prime_max;
  1256.   unsigned char huge *color;
  1257.   unsigned char huge *base_z;
  1258.   int                solve;
  1259.     {  
  1260.       static   double        aspect_ratio;
  1261.       static   double        box_delta_x;
  1262.       static   double        box_delta_y;
  1263.       static   box_rec       box [4];
  1264.       static   int           box_num_1;
  1265.       static   int           box_num_2;
  1266.       static   double        box_x_intercept;
  1267.       static   int           box_x1;
  1268.       static   int           box_x2;
  1269.       static   int           box_y_max;
  1270.       static   int           box_y_min;
  1271.       static   double        box_y_offset;
  1272.       static   int           box_y1;
  1273.       static   short         color_num;
  1274.       static   int           intercept_count_mod_2;
  1275.       register int           line_x1;
  1276.       register int           line_x2;
  1277.       static   double        pixels_per_unit;
  1278.       static   long          prime_num;
  1279.       static   int           solution;
  1280.       static   vertex_rec    vertex [4];
  1281.       static   int           x_division_num;
  1282.       static   long          x_prime_num;
  1283.       static   int           y_division_num;
  1284.       static   double        y_offset;
  1285.       static   double        y_out_max;
  1286.       static   double        z_offset;
  1287.       static   double        z_out_max;
  1288.  
  1289.       aspect_ratio=(HEIGHT_OF_SCREEN/WIDTH_OF_SCREEN)
  1290.        /(((double) NUM_Y_PIXELS)/((double) NUM_X_PIXELS));
  1291.       y_out_max=(double) (NUM_X_PIXELS-1);
  1292.       z_out_max=(double) (NUM_Y_PIXELS-1);
  1293.       if (aspect_ratio*z_out_max*(y_prime_max-y_prime_min)
  1294.        > y_out_max*(z_prime_max-z_prime_min))
  1295.         {
  1296.           pixels_per_unit
  1297.            =y_out_max/(aspect_ratio*(y_prime_max-y_prime_min));
  1298.           y_offset=0.0;
  1299.           z_offset
  1300.            =-(z_out_max-pixels_per_unit*(z_prime_max-z_prime_min))/2.0;
  1301.         }
  1302.       else
  1303.         if (aspect_ratio*z_out_max*(y_prime_max-y_prime_min)
  1304.          < y_out_max*(z_prime_max-z_prime_min))
  1305.           {
  1306.             pixels_per_unit=z_out_max/(z_prime_max-z_prime_min);
  1307.             y_offset=(y_out_max
  1308.              -aspect_ratio*pixels_per_unit*(y_prime_max-y_prime_min))/2.0;
  1309.             z_offset=0.0;
  1310.           }
  1311.         else
  1312.           {
  1313.             pixels_per_unit=1.0;
  1314.             y_offset=y_out_max/2.0;
  1315.             z_offset=-z_out_max/2.0;
  1316.           };
  1317.       for (x_prime_num=0l; x_prime_num < num_primes; x_prime_num++)
  1318.         {
  1319.           x_division_num=x_division_index[x_prime_num];
  1320.           if (x_division_num < (num_x_divisions-1))
  1321.             {
  1322.               y_division_num=y_division_index[x_prime_num];
  1323.               if (y_division_num < (num_y_divisions-1))
  1324.                 {
  1325.                   prime_num
  1326.                    =((long) num_y_divisions)*((long) x_division_num)
  1327.                    +((long) y_division_num);
  1328.                   color_num=(short) (color[prime_num]);
  1329.                   if (color_num < NUM_COLORS)
  1330.                     {
  1331.                       vertex[0].y=(double) (y_prime[prime_num]);
  1332.                       vertex[0].z=(double) (z_prime[prime_num]);
  1333.                       solution=(base_z[prime_num] == (unsigned char) 2);
  1334.                       prime_num+=((long) num_y_divisions);
  1335.                       vertex[1].y=(double) (y_prime[prime_num]);
  1336.                       vertex[1].z=(double) (z_prime[prime_num]);
  1337.                       if (solution)
  1338.                         solution=(base_z[prime_num] == (unsigned char) 2);
  1339.                       prime_num++;
  1340.                       vertex[2].y=(double) (y_prime[prime_num]);
  1341.                       vertex[2].z=(double) (z_prime[prime_num]);
  1342.                       if (solution)
  1343.                         solution=(base_z[prime_num] == (unsigned char) 2);
  1344.                       prime_num-=((long) num_y_divisions);
  1345.                       vertex[3].y=(double) (y_prime[prime_num]);
  1346.                       vertex[3].z=(double) (z_prime[prime_num]);
  1347.                       if (solution)
  1348.                         solution=(base_z[prime_num] == (unsigned char) 2);
  1349.                       if ((! solve) || (solution))
  1350.                         {
  1351.                           if (solve)
  1352.                             color_num=(short) (NUM_COLORS-1);
  1353.                           for (box_num_1=0; box_num_1 < 4; box_num_1++)
  1354.                             {
  1355.                               box[box_num_1].x=(int) (y_offset
  1356.                                +pixels_per_unit*aspect_ratio
  1357.                                *(vertex[box_num_1].y-y_prime_min));
  1358.                               box[box_num_1].y=(int) (z_offset+z_out_max
  1359.                                -pixels_per_unit
  1360.                                *(vertex[box_num_1].z-z_prime_min));
  1361.                             }
  1362.                           box_y_min=box[0].y;
  1363.                           box_y_max=box_y_min;
  1364.                           for (box_num_1=1; box_num_1 < 4; box_num_1++)
  1365.                             {
  1366.                               if (box[box_num_1].y < box_y_min)
  1367.                                 box_y_min=box[box_num_1].y;
  1368.                               if (box[box_num_1].y > box_y_max)
  1369.                                 box_y_max=box[box_num_1].y;
  1370.                             }
  1371.                           for (box_y1=box_y_min; box_y1 <= box_y_max; ++box_y1)
  1372.                             {
  1373.                               intercept_count_mod_2=0;
  1374.                               box_num_2=1;
  1375.                               for (box_num_1=0; box_num_1 < 4; ++box_num_1)
  1376.                                 {
  1377.                                   if (box[box_num_1].y >= box_y1)
  1378.                                     {
  1379.                                       if (box_y1 > box[box_num_2].y)
  1380.                                         {
  1381.                                           box_delta_y=(double)
  1382.                                            (box[box_num_2].y-box[box_num_1].y);
  1383.                                           box_delta_x=(double)
  1384.                                            (box[box_num_2].x-box[box_num_1].x);
  1385.                                           box_y_offset=(double)
  1386.                                            (box_y1-box[box_num_1].y);
  1387.                                           box_x_intercept
  1388.                                            =(double) (box[box_num_1].x);
  1389.                                           box_x1
  1390.                                            =(int) ((box_delta_x*box_y_offset)
  1391.                                            /box_delta_y+box_x_intercept);
  1392.                                           if (intercept_count_mod_2 == 0)
  1393.                                             box_x2=box_x1;
  1394.                                           else
  1395.                                             {
  1396.                                               if (box_x1 < box_x2)
  1397.                                                 {
  1398.                                                   line_x1=box_x1;
  1399.                                                   line_x2=box_x2;
  1400.                                                 }
  1401.                                               else
  1402.                                                 {
  1403.                                                   line_x1=box_x2;
  1404.                                                   line_x2=box_x1;
  1405.                                                 }
  1406.                                               set_pixel(line_x1,box_y1,
  1407.                                                color_num);
  1408.                                               while (line_x1 < line_x2)
  1409.                                                 {
  1410.                                                   line_x1++;
  1411.                                                   set_pixel(line_x1,box_y1,
  1412.                                                    color_num);
  1413.                                                 }
  1414.                                             }
  1415.                                           intercept_count_mod_2
  1416.                                            =1-intercept_count_mod_2;
  1417.                                         }
  1418.                                     }
  1419.                                   else
  1420.                                     {
  1421.                                       if (box_y1 <= box[box_num_2].y)
  1422.                                         {
  1423.                                           box_delta_y=(double)
  1424.                                            (box[box_num_2].y-box[box_num_1].y);
  1425.                                           box_delta_x=(double)
  1426.                                            (box[box_num_2].x-box[box_num_1].x);
  1427.                                           box_y_offset=(double)
  1428.                                            (box_y1-box[box_num_1].y);
  1429.                                           box_x_intercept
  1430.                                            =(double) (box[box_num_1].x);
  1431.                                           box_x1
  1432.                                            =(int) ((box_delta_x*box_y_offset)
  1433.                                            /box_delta_y+box_x_intercept);
  1434.                                           if (intercept_count_mod_2 == 0)
  1435.                                             box_x2=box_x1;
  1436.                                           else
  1437.                                             {
  1438.                                               if (box_x1 < box_x2)
  1439.                                                 {
  1440.                                                   line_x1=box_x1;
  1441.                                                   line_x2=box_x2;
  1442.                                                 }
  1443.                                               else
  1444.                                                 {
  1445.                                                   line_x1=box_x2;
  1446.                                                   line_x2=box_x1;
  1447.                                                 }
  1448.                                               set_pixel(line_x1,box_y1,
  1449.                                                color_num);
  1450.                                               while (line_x1 < line_x2)
  1451.                                                 {
  1452.                                                   line_x1++;
  1453.                                                   set_pixel(line_x1,box_y1,
  1454.                                                    color_num);
  1455.                                                 }
  1456.                                             }
  1457.                                           intercept_count_mod_2
  1458.                                            =1-intercept_count_mod_2;
  1459.                                         }
  1460.                                     }
  1461.                                   box_num_2++;
  1462.                                   if (box_num_2 >= 4)
  1463.                                     box_num_2=0;
  1464.                                 }
  1465.                             }
  1466.                         }
  1467.                     }
  1468.                 }
  1469.             }
  1470.         }
  1471.       return;
  1472.     }
  1473.  
  1474. static double f(x,y)
  1475.   double x;
  1476.   double y;
  1477.     {
  1478.       static   int    solution;
  1479.       register int    x_next;
  1480.       static   int    x_offset;
  1481.       static   int    x_out;
  1482.       static   int    y_next;
  1483.       register int    y_offset;
  1484.       static   int    y_out;
  1485.       static   double z;
  1486.  
  1487.       y_out=(int) x;
  1488.       y_next=--y_out;
  1489.       y_out/=(2*RESOLUTION);
  1490.       if (4*(y_next-2*RESOLUTION*y_out) >= 5*RESOLUTION)
  1491.         y_out+=y_out;
  1492.       else
  1493.         {
  1494.           y_out+=y_out;
  1495.           y_out--;
  1496.         }
  1497.       if (y_out < 0)
  1498.         z=0.0;
  1499.       else
  1500.         if (y_out > MAX_Y)
  1501.           z=0.0;
  1502.         else
  1503.           {
  1504.             x_out=(int) y;
  1505.             x_next=--x_out;
  1506.             x_out/=(2*RESOLUTION);
  1507.             if (4*(x_next-2*RESOLUTION*x_out) >= 5*RESOLUTION)
  1508.               x_out+=x_out;
  1509.             else
  1510.               {
  1511.                 x_out+=x_out;
  1512.                 x_out--;
  1513.               }
  1514.             if (x_out < 0)
  1515.               z=0.0;
  1516.             else
  1517.               if (x_out > MAX_X)
  1518.                 z=0.0;
  1519.               else
  1520.                 if (page[y_out][x_out] == 'W')
  1521.                   {
  1522.                     solution=FALSE;
  1523.                     for (x_offset=-1; x_offset <= 1; x_offset++)
  1524.                       for (y_offset=-1; y_offset <= 1; y_offset++)
  1525.                         if (x_offset != 0)
  1526.                           {
  1527.                             x_next=x_out+x_offset;
  1528.                             y_next=y_out+y_offset;
  1529.                             if ((x_next >= 0)
  1530.                             &&  (x_next <= MAX_X)
  1531.                             &&  (y_next >= 0)
  1532.                             &&  (y_next <= MAX_Y)
  1533.                             &&  (page[y_next][x_next] == 'S'))
  1534.                               solution=TRUE;
  1535.                           }
  1536.                         else
  1537.                           {
  1538.                             if (y_offset != 0)
  1539.                               {
  1540.                                 x_next=x_out+x_offset;
  1541.                                 y_next=y_out+y_offset;
  1542.                                 if ((x_next >= 0)
  1543.                                 &&  (x_next <= MAX_X)
  1544.                                 &&  (y_next >= 0)
  1545.                                 &&  (y_next <= MAX_Y)
  1546.                                 &&  (page[y_next][x_next] == 'S'))
  1547.                                   solution=TRUE;
  1548.                               }
  1549.                           };
  1550.                     z=15.0;
  1551.                     if (solution)
  1552.                       z=-z;
  1553.                   }
  1554.                 else
  1555.                   z=0.0;
  1556.  
  1557.           }
  1558.       return(z);
  1559.     }
  1560.  
  1561. static void free_memory(x_prime,y_prime,z_prime,x_division_index,
  1562.  y_division_index,color,base_z)
  1563.   float huge         **x_prime;
  1564.   float huge         **y_prime;
  1565.   float huge         **z_prime;
  1566.   int   huge         **x_division_index;
  1567.   int   huge         **y_division_index;
  1568.   unsigned char huge **color;
  1569.   unsigned char huge **base_z;
  1570.     {
  1571.       hfree((void huge *) *base_z);
  1572.       hfree((void huge *) *color);
  1573.       hfree((void huge *) *y_division_index);
  1574.       hfree((void huge *) *x_division_index);
  1575.       hfree((void huge *) *z_prime);
  1576.       hfree((void huge *) *y_prime);
  1577.       hfree((void huge *) *x_prime);
  1578.       return;
  1579.     }
  1580.  
  1581. static int VGA_640_480_16()
  1582.   {
  1583.     static char          *buffer;
  1584.     static USHORT        cell_num;
  1585.     static int           color_num;
  1586.     static int           plane_num;
  1587.     static int           result;
  1588.     static unsigned char tint;
  1589.  
  1590.     /* Allocate memory to save screen when it's switched. */
  1591.     result=TRUE;
  1592.     for (plane_num=0; ((result) && (plane_num < 4)); plane_num++)
  1593.       result=((video_plane[plane_num]
  1594.        =(long huge *) halloc(NUM_CELLS,sizeof(char))) != NULL);
  1595.  
  1596.     if (result)
  1597.       {
  1598.         VioScrLock((USHORT) LOCKIO_WAIT,(PBYTE) &scr_lock,(HVIO) 0);
  1599.     
  1600.         /* Save current video mode. */
  1601.         default_video_mode.cb=sizeof(VIOMODEINFO);
  1602.         VioGetMode((PVIOMODEINFO) &default_video_mode,(HVIO) 0);
  1603.     
  1604.         /* Switch to 640 x 480 x 16 VGA mode. */
  1605.         memcpy((void *) &maze_video_mode,(const void *) &default_video_mode,
  1606.          sizeof(VIOMODEINFO));
  1607.         maze_video_mode.fbType=VGMT_GRAPHICS|VGMT_OTHER;
  1608.         maze_video_mode.color=COLORS_16;
  1609.         maze_video_mode.col=80;
  1610.          maze_video_mode.row=25;
  1611.         maze_video_mode.hres=NUM_X_PIXELS;
  1612.         maze_video_mode.vres=NUM_Y_PIXELS;
  1613.         if (result=(VioSetMode((PVIOMODEINFO) &maze_video_mode,(HVIO) 0)
  1614.          == (USHORT) 0))
  1615.           {
  1616.             /* Set up palette for invisible screen redraw. */
  1617.             invisible_palette=(PVIOPALSTATE) &invisible_palette_byte[0];
  1618.             invisible_palette->cb=(USHORT) sizeof(invisible_palette_byte);
  1619.             invisible_palette->type=(USHORT) 0;
  1620.             invisible_palette->iFirst=(USHORT) 0;
  1621.             for (color_num=0; color_num < NUM_COLORS; color_num++)
  1622.               invisible_palette->acolor[color_num]=(USHORT) 0;
  1623.     
  1624.             /* Set up shades of gray, etc. for drawing maze. */
  1625.             maze_palette=(PVIOPALSTATE) &maze_palette_byte[0];
  1626.             maze_palette->cb=(USHORT) sizeof(maze_palette_byte);
  1627.             maze_palette->type=(USHORT) 0;
  1628.             maze_palette->iFirst=(USHORT) 0;
  1629.             for (color_num=0; color_num < NUM_COLORS; color_num++)
  1630.               maze_palette->acolor[color_num]=(USHORT) color_num;
  1631.             VioSetState(maze_palette,(HVIO) 0);
  1632.             maze_color.cb=(USHORT) sizeof(maze_color);
  1633.             maze_color.type=(USHORT) 3;
  1634.             maze_color.firstcolorreg=(USHORT) 0;
  1635.             maze_color.numcolorregs=(USHORT) NUM_COLORS;
  1636.             maze_color.colorregaddr=(PCH) &maze_rgb[0];
  1637.             tint=(unsigned char) 0;
  1638.             for (color_num=0; color_num < (NUM_COLORS-1); color_num++)
  1639.               {
  1640.                 maze_rgb[color_num].red=tint;
  1641.                 maze_rgb[color_num].green=tint;
  1642.                 maze_rgb[color_num].blue=tint;
  1643.                 tint+=((unsigned char) RGB_INCREMENT);
  1644.               }
  1645.             maze_rgb[color_num].red=tint;
  1646.             maze_rgb[color_num].green=(unsigned char) 0;
  1647.             maze_rgb[color_num].blue=(unsigned char) 0;
  1648.             VioSetState(&maze_color,(HVIO) 0);
  1649.     
  1650.             /* Locate physical video buffer. */
  1651.             FP_SEG(phys_buf.pBuf)=0x000a;
  1652.             FP_OFF(phys_buf.pBuf)=0;
  1653.             phys_buf.cb=NUM_CELLS;
  1654.             VioGetPhysBuf((PVIOPHYSBUF) &phys_buf,(USHORT) 0);
  1655.             VGA_base_adr=phys_buf.asel[0];
  1656.     
  1657.             /* Clear screen. */
  1658.             FP_SEG(buffer)=phys_buf.asel[0];
  1659.             for (cell_num=(USHORT) 0; cell_num < (USHORT) NUM_CELLS; cell_num++)
  1660.               {
  1661.                 FP_OFF(buffer)=cell_num;
  1662.                 *buffer='\0';
  1663.               }
  1664.     
  1665.             /* Start thread to save/redraw screen when screen is switched. */
  1666.             DosCreateThread((PFNTHREAD) save_redraw_thread,
  1667.              (PTID) &save_redraw_id,(PBYTE) 
  1668.              (save_redraw_thread_stack+sizeof(save_redraw_thread_stack)));
  1669.     
  1670.             /* Start thread to keep screen in 640 x 480 x 16 VGA mode. */
  1671.             DosCreateThread((PFNTHREAD) mode_thread,
  1672.              (PTID) &mode_thread_stack,
  1673.              (PBYTE) (mode_thread_stack+sizeof(mode_thread_stack)));
  1674.           }
  1675.         VioScrUnLock((HVIO) 0);
  1676.       }
  1677.     return(result);
  1678.   }
  1679.  
  1680. static void set_initial_video_mode()
  1681.   {
  1682.     VioScrLock((USHORT) LOCKIO_WAIT,(PBYTE) &scr_lock,(HVIO) 0);
  1683.     VioSetMode((PVIOMODEINFO) &default_video_mode,(HVIO) 0);
  1684.     VioScrUnLock((HVIO) 0);
  1685.     hfree((void huge *) (video_plane[3]));
  1686.     hfree((void huge *) (video_plane[2]));
  1687.     hfree((void huge *) (video_plane[1]));
  1688.     hfree((void huge *) (video_plane[0]));
  1689.     return;
  1690.   }
  1691.  
  1692. static void set_pixel(x,y,color)
  1693.   int   x;
  1694.   int   y;
  1695.   short color;
  1696.     {
  1697.       int   bit_mask;
  1698.       char  *cell;
  1699.       int   dummy;
  1700.     
  1701.       VioScrLock((USHORT) LOCKIO_WAIT,(PBYTE) &scr_lock,(HVIO) 0);
  1702.       FP_SEG(cell)=VGA_base_adr;
  1703.       FP_OFF(cell)=y*80+x/8;
  1704.       bit_mask=0x80>>(x % 8);
  1705.       outp(VGA_control,VGA_bit_mask);
  1706.       outp(VGA_control_data,bit_mask);
  1707.       outp(VGA_control,VGA_mode);
  1708.       outp(VGA_control_data,2);
  1709.       dummy=*cell; 
  1710.       *cell=(char) color;
  1711.       outp(VGA_control,VGA_mode);
  1712.       outp(VGA_control_data,0);
  1713.       outp(VGA_control,VGA_bit_mask);
  1714.       outp(VGA_control_data,0xff);
  1715.       VioScrUnLock((HVIO) 0);
  1716.       return;
  1717.     }
  1718.  
  1719. static void save_redraw_thread()
  1720.   {
  1721.     long         *buffer;
  1722.     unsigned     count;
  1723.     long         dummy;
  1724.     VIOMODEINFO  mode_info; 
  1725.     int          plane_num;
  1726.     int          power_of_2;
  1727.     int          save_redraw_cmd;
  1728.  
  1729.     while (TRUE)
  1730.       {
  1731.         VioSavRedrawWait(VSRWI_SAVEANDREDRAW,&save_redraw_cmd,0);
  1732.         if (save_redraw_cmd == VSRWN_SAVE)
  1733.           {
  1734.             /* Save a copy of the screen mode. */
  1735.             mode_info.cb=sizeof(VIOMODEINFO);
  1736.             VioGetMode((PVIOMODEINFO) &mode_info,(HVIO) 0);
  1737.  
  1738.             /* Save the contents of the screen. */
  1739.             FP_SEG(buffer)=VGA_base_adr;
  1740.             for (plane_num=0; plane_num < 4; plane_num++)
  1741.               {
  1742.                 outp(VGA_control,VGA_read_map);
  1743.                 outp(VGA_control_data,plane_num);
  1744.                 for (count=0; count < NUM_CELLS; count+=4)
  1745.                   {
  1746.                     FP_OFF(buffer)=count;
  1747.                     (video_plane[plane_num])[count>>2]=*buffer;
  1748.                   }
  1749.               }
  1750.  
  1751.             outp(VGA_sequence,VGA_map_mask); 
  1752.             outp(VGA_sequence_data,0xff);
  1753.           }
  1754.         else
  1755.           {
  1756.             /* Restore the screen mode. */
  1757.             VioSetMode((PVIOMODEINFO) &mode_info,(HVIO) 0);
  1758.  
  1759.             /* Set the screen up for invisible restore. */
  1760.             VioSetState((PVOID) invisible_palette,(HVIO) 0);
  1761.  
  1762.             /* Reset the colors. */
  1763.             VioSetState((PVOID) &maze_color,(HVIO) 0);
  1764.  
  1765.             /* Restore the screen. */
  1766.             FP_SEG(buffer)=VGA_base_adr;
  1767.             power_of_2=1;
  1768.             for (plane_num=0; plane_num < 4; plane_num++)
  1769.               {
  1770.                 outp(VGA_sequence,VGA_map_mask);
  1771.                 outp(VGA_sequence_data,power_of_2);
  1772.                 for (count=0; count < NUM_CELLS; count+=4)
  1773.                   {
  1774.                     FP_OFF(buffer)=count;
  1775.                     dummy=*buffer;
  1776.                     *buffer=(video_plane[plane_num])[count>>2];
  1777.                   }
  1778.                 power_of_2*=2;
  1779.               }
  1780.  
  1781.             outp(VGA_sequence,VGA_map_mask);
  1782.             outp(VGA_sequence_data,0xff);
  1783.  
  1784.             /* Make the screen visible. */
  1785.             VioSetState((PVOID) maze_palette,(HVIO) 0);
  1786.           }
  1787.       }
  1788.     return;
  1789.   }
  1790.  
  1791. static void mode_thread()
  1792.   {
  1793.     USHORT mode_cmd;
  1794.  
  1795.     while (TRUE)
  1796.       {
  1797.         VioModeWait((USHORT) 0,(PUSHORT) &mode_cmd,(HVIO) 0);
  1798.         VioSetMode((PVIOMODEINFO) &maze_video_mode,(HVIO) 0);
  1799.       }
  1800.     return;
  1801.   }
  1802.